/*
 * @[H]:  Copyright (c) 2021 Phytium Information Technology, Inc. 
 * 
 *  SPDX-License-Identifier: Apache-2.0. 
 * 
 * @Date: 2021-08-17 10:54:17
 * @LastEditTime: 2021-08-25 09:06:53
 * @Description:  Description of file
 * @Modify History: 
 * * * Ver   Who        Date         Changes
 * * ----- ------     --------    --------------------------------------
 */

#ifndef DRIVERS_FGDMA_H
#define DRIVERS_FGDMA_H

#include "ft_types.h"
#include "parameters.h"
#include "ft_assert.h"
#include "fgdma_bdl.h"

#define FGMDA_ERR_OP FT_CODE_ERR(ErrModBsp, ErrGdma, 0x1u)

#ifdef __aarch64__
typedef u64 FGdmaAddr;
#else
typedef u32 FGdmaAddr;
#endif

#define FGDMA_CHANNEL_MAX_NUM FGDMA_CH_NUM

/* Transfer priority ,A larger value indicates a higher priority*/
#define FGDMA_TRANSFER_PRIORITY0 0
#define FGDMA_TRANSFER_PRIORITY1 1
#define FGDMA_TRANSFER_PRIORITY2 2
#define FGDMA_TRANSFER_PRIORITY3 3
#define FGDMA_TRANSFER_PRIORITY4 4
#define FGDMA_TRANSFER_PRIORITY5 5
#define FGDMA_TRANSFER_PRIORITY6 6
#define FGDMA_TRANSFER_PRIORITY7 7
#define FGDMA_TRANSFER_PRIORITY8 8
#define FGDMA_TRANSFER_PRIORITY9 9
#define FGDMA_TRANSFER_PRIORITY10 10
#define FGDMA_TRANSFER_PRIORITY11 11
#define FGDMA_TRANSFER_PRIORITY12 12
#define FGDMA_TRANSFER_PRIORITY13 13
#define FGDMA_TRANSFER_PRIORITY14 14
#define FGDMA_TRANSFER_PRIORITY15 15

/* Dma transter direction  */
#define FGDMA_MEM_TO_MEM 0
#define FGDMA_MEM_TO_DEV 1
#define FGDMA_DEV_TO_MEM 2

/* Brust width */
#define FGDMA_SLAVE_BUSWIDTH_1_BYTE 1
#define FGDMA_SLAVE_BUSWIDTH_2_BYTES 2
#define FGDMA_SLAVE_BUSWIDTH_4_BYTES 4
#define FGDMA_SLAVE_BUSWIDTH_8_BYTES 8
#define FGDMA_SLAVE_BUSWIDTH_16_BYTES 16

/* Option */
#define FGDMA_OP_WRITE_QOS_MODE 0
#define FGDMA_OP_READ_QOS_MODE 1

/* Transfer data type */
#define FGDMA_TRANS_CONTINUOUS_MEMORY 0
#define FGDMA_TRANS_BDL 1

/* Irq status */
#define FGDMA_IRQ_STATUS_FIFO_EMPTY 0
#define FGDMA_IRQ_STATUS_FIFO_FULL 1
#define FGDMA_IRQ_STATUS_BDL_END 2
#define FGDMA_IRQ_STATUS_TRANS_END 3
#define FGDMA_IRQ_STATUS_BUSY 4
#define FGDMA_IRQ_STATUS_OTHER 5

typedef void (*FGdmaChxIrqStatus)(u32 status, void *args);

typedef struct
{
    u32 dma_src_addr_l;
    u32 dma_src_addr_h;
    u32 dma_dst_addr_l; // For direct
    u32 dma_dst_addr_h; // For direct
    u32 data_len;       // For direct
    u32 direction;      // Direction of data transmission
} FGdmaDataConfig;

typedef struct
{
    volatile uintptr_t dma_channel_addr; /* dma channel addr */
    u32 priority;
    u32 src_addr_width; /* this is the width in bytes of the source (RX) register where DMA data shall be read.  */
    u32 dst_addr_width; /*  same as src_addr_width but for destination target (TX) mutatis mutandis. */
    u32 src_maxburst;   /* the maximum number of words (note: words, as in units of the src_addr_width member, not bytes) that can be sent in one burst to the device. */
    u32 dst_maxburst;   /* same as src_maxburst but for destination target mutatis mutandis. */

} FGdmaChConfig;

typedef struct
{
    u32 instance_id;                                         /* Id of device */
    u32 irq_num;                                             /* Irq number */
    volatile uintptr_t base_address;                         /* The Memory way */
    FGdmaChConfig dma_channel_config[FGDMA_CHANNEL_MAX_NUM]; /* dma channel info */
} FGdmaConfig;

typedef struct
{
    u32 is_ready; /* Device is ininitialized and ready*/
    FGdmaConfig config;
    FGdmaChxIrqStatus irq_status_cb;
    void *irq_status_args;
} FGdma;

FGdmaConfig *FGdmaLookupConfig(u32 instance_id);
/**
     * @name: FGdmaCfgInitialize
     * @msg:   This function initializes a Gdma instance/driver.
     * @param {FGdma} *instance_p is a pointer to the FGdma instance.
     * @param {FGdmaConfig} *config_p  points to the FGdma device configuration structure.
     * @return {*}
     */
ft_error_t FGdmaCfgInitialize(FGdma *instance_p, FGdmaConfig *config_p);

/**
 * @name: FGdmaTransfer
 * @msg: This function does one simple transfer in direct mode
 * @param {FGdma} *instance_p is a pointer to the FGdma instance.
 * @param {FGdmaChIndex} index is Gdma channel select
 * @param {FGdmaDataConfig} * data_config_p  is a direct send mode data structure
 * @return {*}
 */
ft_error_t FGdmaTransfer(FGdma *instance_p, FGdmaChIndex index,
                         FGdmaDataConfig *data_config_p);

/**
 * @name: FGdmaBdlTransfer
 * @msg:  This function does one simple transfer in Bdl mode
 * @param {FGdma} *instance_p is a pointer to the FGdma instance.
 * @param {FGdmaChIndex} index is the channel to be transfer
 * @param {u32} direction is the memory transfer direction , followed by FGDMA_MEM_TO_MEM
 * @return {*}
 */
ft_error_t FGdmaBdlTransfer(FGdma *instance_p, FGdmaChIndex index,
                            u32 direction, struct FGdmaBdlDesc *bdl_desc_p,
                            u32 desc_num);

/**
 * @name: FGdmaSetOption
 * @msg:  This function sets the options for the Gdma device driver.
 * @param {FGdma} *instance_p is a pointer to the FGdma instance.
 * @param {u32} options contains the specified options to be set.
 * @return {*}
 */
ft_error_t FGdmaSetOption(FGdma *instance_p, u32 options);

/**
 * @name: FGdmaChEnable
 * @msg:  Enable the specified DMA Channel. 
 * @param {FGdma} *instance_p  is a pointer to the FGdma instance.
 * @param {FGdmaChIndex} index is the channel to be enable.
 * @return {*}
 */
void FGdmaChEnable(FGdma *instance_p, FGdmaChIndex index);
/**
 * @name: FGdmaChIrqEnable
 * @msg:  Enable the specified DMA Channel Irq.
 * @param {FGdma} *instance_p is a pointer to the FGdma instance
 * @param {FGdmaChIndex} index is the channel to be enable.
 * @return {*}
 */
void FGdmaChIrqEnable(FGdma *instance_p, FGdmaChIndex index);

/**
 * @name: FGdmaChBdlIrqEnable
 * @msg:  Enable the specified DMA Channel Bdl Irq.
 * @param {FGdma} *instance_p is a pointer to the FGdma instance
 * @param {FGdmaChIndex} index is the channel to be enable.
 * @return {*}
 */
void FGdmaChBdlIrqEnable(FGdma *instance_p, FGdmaChIndex index);

/* Irq */
void FGdmaIrqDisable(FGdma *instance_p);
void FGdmaIrqEnable(FGdma *instance_p);
void FGdmaIrqHandler(s32 vector, void *args);
ft_error_t FGdmaIrqSetHandler(FGdma *instance_p, void *func_pointer, void *call_back_ref);
#endif // !